package com.mall.mymall.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mall.mymall.common.ProductRepository;
import com.mall.mymall.dao.dto.ProductDto;
import com.mall.mymall.dao.dto.QueryDto;
import com.mall.mymall.dao.dto.querypage.ProductPageRequest;
import com.mall.mymall.dao.entity.Products;
import com.mall.mymall.mapper.ProductsMapper;
import com.mall.mymall.service.ProductsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mall.mymall.utils.ProductsElasticSearchUtil;
import com.mall.mymall.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 十里坡
 * @since 2025-03-06
 */
@Service
public class ProductsServiceImpl extends ServiceImpl<ProductsMapper, Products> implements ProductsService {

    @Autowired
    private ProductRepository repository;

    @Autowired
    private ThreadPoolTaskExecutor executor;

    @Autowired
    private ProductsElasticSearchUtil elasticSearchUtil;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public QueryDto<ProductDto> pageProducts(ProductPageRequest productPageRequest) {
        // 创建分页对象
        Page<ProductDto> page = new Page<>(productPageRequest.getPageRequestDto().getPage(), productPageRequest.getPageRequestDto().getSize());

        // 执行自定义分页查询
        IPage<ProductDto> resultPage = this.baseMapper.selectProductsPage(page, productPageRequest.getQuery());

        // 构造返回结果
        QueryDto<ProductDto> result = new QueryDto<>();
        result.setTotal((int) resultPage.getTotal());
        result.setRecords(resultPage.getRecords());

        return result;
    }

    @Override
    public Boolean updateProductImage(Long productId, String image) {

        this.baseMapper.updateProductImage(productId, image);
        return true;
    }

    /**
     * 查询商品列表
     *
     * @param keyword 查询内容
     * @return 返回结果集
     */
    @Override
    public List<Products> SearchProducts(String keyword) {
        // 如果关键词为空或无效，直接返回空列表
        if (keyword == null || keyword.isEmpty()) {
            return List.of();
        }

        // 首先尝试从 Elasticsearch 中查询
        List<Products> products = searchFromElasticSearch(keyword);
        if (!products.isEmpty()) {
            return products; // 如果 ES 中有数据，直接返回
        }
        // 尝试从缓存中获取
        products = redisUtils.getProductListByKey(keyword);
        if (!products.isEmpty()) {
            // 表示命中redis
            submitProductsToElasticSearch(products);
            return products;
        }
        // 如果 ES 中没有数据，则从数据库中查询
        products = searchFromDatabase(keyword);
        if (!products.isEmpty()) {
            // 如果数据库中有数据，提交到 ES 中
            submitProductsToElasticSearch(products);
            // 提交到redis
            submitProductsToRedis(keyword, products);
        }

        return products;
    }

    // 从 Elasticsearch 中查询产品
    private List<Products> searchFromElasticSearch(String keyword) {
        return repository.searchText(keyword);
    }

    // 从数据库中查询产品
    private List<Products> searchFromDatabase(String keyword) {
        return this.baseMapper.search(keyword);
    }

    // 将产品提交到 Elasticsearch
    private void submitProductsToElasticSearch(List<Products> products) {
        executor.execute(() -> {
            elasticSearchProductsSubmit(products);
        });
    }

    // 提交redis
    private void submitProductsToRedis(String Key, List<Products> products) {
        executor.execute(() -> {
            RedisSearchProductsSubmit(Key, products);
        });
    }

    /**
     * 提交数据到es中
     *
     * @param products 表示提交的数据
     */
    public void elasticSearchProductsSubmit(List<Products> products) {
        try {
            elasticSearchUtil.batchInsert(products);
        } catch (Exception e) {
            log.error("批量插入失败", e);
        }
    }

    /**
     * 提交到redis
     *
     * @param key
     * @param list
     */
    public void RedisSearchProductsSubmit(String key, List<Products> list) {
        try {
            redisUtils.setSearchListToRedis(key, list);
        } catch (Exception e) {
            log.error("缓存失败", e);
        }
    }
}
